#!/usr/bin/python
#coding:utf-8
#@author luma
#@email 270377471@qq.com
#@date 2015.6.30


from functools import wraps
import sys
import json
import requests
import sys
from optparse import OptionParser


def CheckLogin(func):
    def wrapper(self,*args,**kwargs):
        if not self.__checkauth__():
            sys.exit('Not Login!')
        return func(self,*args,**kwargs)
    return wrapper


class Zabbix(object):
    """ A Zabbix Simple Python API on v2.6  """
    uri = '/api_jsonrpc.php'

    def __init__(self,ipaddr,timeout=300):
        self.ipaddr = ipaddr
        self.url = self.ipaddr+self.uri
        self.timeout = timeout
        self.auth=''

    def Login(self,user,passwd):
        obj = self.DoJSON('user.login',{'user':user, 'password': passwd},auth=False)
        self.auth = self.DoRequest(obj)

    def __checkauth__(self):
        if self.auth:
            return True
        return False


    def DoJSON(self,method,params={},auth=True):
        obj = {
            'jsonrpc': '2.0',
            'method': method,
            'params': params,
            'auth': self.auth,
             'id': 1
        }
        if not auth:del obj['auth']

        return json.dumps(obj)


    def DoRequest(self,params):
        headers = {"Content-Type": "application/json;charset=utf-8"}
        try:
            response = requests.post(self.url,data=params,headers=headers,timeout=self.timeout)
        except Exception, e:
            print 'exception: %s' % e
        else:
            if response.status_code != 200:
                print 'request error %s' % response.status_code
            try:
                #print response.text
                rsp = json.loads(response.text)
                if rsp.has_key('error'):
                   print rsp['error']
                else:
                   return  rsp['result']
            except Exception,e:
                print e

    @CheckLogin
    def DoAction(self,method,params):
        o = self.DoJSON(method,params)
        return self.DoRequest(o)


'''check item exists'''
def CheckExist(method):
    item = method.split('.')[0].capitalize()
    def decorator(fn):
        @wraps(fn) 
        def wrapper(self,*args,**kwargs):
            kw = args[0]
            _index = ['host','name','expression','_key']
            for i in _index:
                if kw.has_key(i):
                    if self.universal(method,{'name':kw.get(i)}):
                        if item == 'Item':
                            print "ERROR::[\033[40;32m%s\033[0m:\033[40;31m%s\033[0m] is already exists" % (kw.get('host'),kw.get('key'))
                        else:
                            print "ERROR::[\033[40;32m%s\033[0m:\033[40;31m%s\033[0m] is already exists" % (item,kw.get(i))
                    else:
                        fn(self,*args,**kwargs)
                    break
        return wrapper
    return decorator

'''import from file '''
def ImportObject(idx,tag):
    def decorator(fn):
        @wraps(fn)
        def wrapper(self,*args,**kwargs):
            file = args[0].get('file')
            m = fn(self,*args,**kwargs)
            with open(file) as f:
                hosts = [ x.strip('\n') for x in f.readlines()]
                if  tag == 'host':
                    for h in hosts:
                        if len(h):L = h.split('\t')
                        L[0] = dict(self.ifcfg,ip=L[0])
                        L[2] = L[2].split(',')
                        L[3] = L[3].split(',')
                        m(dict(zip(idx,L)))
                else:
                    for h in hosts:
                        if len(h):L = h.split('\t') #tab 分割符号
                        m(dict(zip(idx,L)))
        return wrapper
    return decorator


class Worker():
    """A Zabbix Worker Class"""

    def __init__(self, url,user='user',password='password',**kw):
        self.zbx = Zabbix(url)
        self.zbx.Login(user,password)
        self.ifcfg = {
            "type": 1,
            "main": 1,
            "useip":1,
            "dns": "",
            "port": "10050"
        }
        if kw.has_key('ifcfg'):self.ifcfg = kw['ifcfg']


    def getTemplateIdByName(self,tname,grep):
        #qc = 'query' if sort else ['name','templateid'] python 三目操作
        '''tname 可以是多个'''
        params = {'output':grep,'filter':{'host':tname}}
        return self.zbx.DoAction('template.get',params),

    def getGroupIdByName(self,grpname,grep):
        params = {'output':grep,'filter':{'name':grpname}}
        return self.zbx.DoAction('hostgroup.get',params)

    def getHostIdByName(self,name,grep):
        params = {'output':grep,'filter':{'host':name}}
        return self.zbx.DoAction('host.get',params)

    def getAppIdByName(self,**kwargs):
        #@kwargs => groupids,hostids,itemids
        #params = {'output':'query','filter'}
        pass

    def getItemIdByHost(self,hosts=[],search={},grep=['query']):
        hostid = self.getHostIdByName(hosts,['hostid'])
        L = [ x['hostid'] for x in hostid]
        params = { 'output':grep,'hostids':L,'search':search}
        return self.zbx.DoAction('item.get',params)

    def getInterfaceIdByHost(self,hostnames,grep):
        hostids = self.getHostIdByName(hostnames,['query'])
        params = {
            'output':grep,
            'hostids':hostids[0]['hostid']
        }
        return self.zbx.DoAction('hostinterface.get',params)

    @CheckExist('host.exists')
    def createHost(self,obj,**kwargs):
        '''@name     主机名称
           @groups   隶属组
           @interfaces 接口配置
           @templates  隶属模板
        '''
        groupids = self.getGroupIdByName(obj.get('groups'),['groupid'])
        templateids = self.getTemplateIdByName(obj.get('templates'),['templateid'])
        params = {
            'host':obj.get('host'),
            'interfaces':[obj.get('interfaces')], ##可以考虑默认属性
            'groups':groupids,
            'templates':templateids[0]
        }
        v = self.zbx.DoAction('host.create',dict(params,**kwargs))
        print '%s  created ' % obj.get('host')
        return v

   
    @ImportObject(['interfaces','host','groups','templates'],'host')
    def importHosts(self,obj):
        print ''' 
                  import file must be contains these fields desc,expression,host
                  and no blank lines,Notice each field separate as Tab,eg:
                  just a test     system.cpu.load[all,avg1]       howge1
              '''
        str = raw_input("Are you sure you file format is right?(y/Y): ")
        if str in ['y','Y']:
            return self.createHost
        else:
            sys.exit('Answer Y or y !')
           
    @CheckExist('hostgroup.exists')
    def createGroup(self,obj):
        '''@name  组名 '''
        v = self.zbx.DoAction('hostgroup.create',obj)
        print 'Hostgroup %s Created!' % obj.get('name')
        return v

    @CheckExist('template.exists')
    def createTemplate(self,obj):
        '''@groups 隶属组名
           @hosts  主机成员
        '''
        groupids = self.getGroupIdByName(obj['groups'],['groupid'])
        hostids = self.getHostIdByName(obj['hosts'],['hostid'])
        params = {
           'host':obj['host'],
           'groups':groupids,
           'hosts':hostids
        }
        return self.zbx.DoAction(params)

    @CheckExist('item.exists')
    def createItems(self,obj,type_v=0,value_type=3,delay=60,**kwargs):
        '''@itemname  item名称
           @key       item 键值
           @hostname  主机名称
        '''
        hostid = self.getHostIdByName(obj['host'],['hostid'])
        ifaceid = self.getInterfaceIdByHost(obj['host'],['query'])
        params = {
            'name' : obj.get('name'),
            'key_' : obj.get('key'),
            'hostid' : hostid[0]['hostid'],
            'type' : type_v,
            'value_type' : value_type,
            'interfaceid' : ifaceid[0]['interfaceid'],
            'delay' : delay
        }
        return self.zbx.DoAction('item.create',params)

    @ImportObject(['name','key','host'],'items')
    def importItems(self,obj):
        print ''' 
                  import file must be contains these fields ip,hostname,groups,templates 
                  and no blank lines,Notice each field separate as Tab,but groups and templates are
                  separated as ',' eg:
                  192.168.120.100 howge12 wanghao Zabbix servers,Template OS Linux
              '''
        str = raw_input("Are you sure you file format is right?(y/Y): ")
        if str in ['y','Y']:
            return self.createItems
        else:
            sys.exit()

    @CheckExist('trigger.exists')
    def createTrigger(self,obj,**kwargs):
        '''@desc 触发器描述
           @exp  表达式
        '''
        params = {
            'description':obj.get('desc'),
            'expression':obj.get('expression'),
            'priority' : obj.get('level')
        }
        return self.zbx.DoAction('trigger.create',dict(params,**kwargs))
    
    @ImportObject(['desc','expression','level'],'trigger')
    def importTrigger(self,obj):
        print '''
                 import file must be contains these fields name,expression,notice level and no blank lines
                 eg:Test Disk I/O is overloaded on {HOST.NAME}      {howge12:system.cpu.util[,iowait].avg(5m)}>30   5
              '''
        str = raw_input("Are you sure you file format is right?(y/Y): ")
        if str in ['y','Y']:
            return  self.createTrigger
        else:
            sys.exit('Answer Y or y')

    def createAPP(self,name='',hostname=''):
        '''@name      应用名称
           @hostname 隶属于主机
        '''
        hostid = self.getHostIdByName(hostname,['hostid'])
        params = {
            'name':name,
            'hostid':hostid
        }
        ext =  self.universal('application.exists',params)
        if not ext:
            return self.zbx.DoAction('application.create',params)
        else:
            print "Application: %s is already exists on host %s" % (name,hostname)

    def universal(self,method,params):
        return self.zbx.DoAction(method,params)
   

    @staticmethod
    def getCLIOpts():
        parser = OptionParser()
        parser.add_option("-X","--action",dest="action",type='choice',action='store',choices=['add','query','del','import'],help="choose a Action in [query,add,del,import] ")
        parser.add_option("-O","--object",dest="object",type='choice',action='store',choices=['host','temp','group','app','item','trigger'],help="add a host,group,tmplate,application or an item ")
        parser.add_option("-H","--host",dest="host",help="hostname",action='append')
        parser.add_option("-T","--template",dest="template",help='Add a Template,some groups within this Template!',action='append')
        parser.add_option("-I","--item",dest="item",help='item must have a key and a host ')
        parser.add_option("-N","--name",dest="name",help='names of object ')
        parser.add_option("-G","--group",dest="group",help='group  name ',action='append')
        parser.add_option("--file",dest="file",help='import object  from file ,specially this option only support Host object')
        parser.add_option("--ipddr",dest="ipaddr",help='ip address')
        parser.add_option("--item-key",dest="ikey",help='item key')
        parser.add_option("--trigger-exp",dest="texp",help='trigger expression')
        parser.add_option("--trigger-level",dest="tlevel",help='trigger notice level')
        parser.add_option("--ifcfg",dest="ifcfg",help='default value is {"type": 1,"main": 1,"useip": 1,"dns": "","port": "10050"}',default={"type": 1,"main": 1,"useip": 1,"dns": "","port": "10050"})
        parser.add_option("--filter",dest="filter",help='get filter field,referrence to  Zabbix API doc',action='append')
        (options, args) = parser.parse_args()
        return (options,parser)
